package com.googlecode.groovycpp.transform

import org.codehaus.groovy.ast.AnnotationNode
import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.MethodNode
import org.codehaus.groovy.ast.ModuleNode
import org.codehaus.groovy.ast.builder.AstBuilder
import org.codehaus.groovy.control.CompilePhase
import org.codehaus.groovy.control.SourceUnit
import org.codehaus.groovy.transform.GroovyASTTransformation

import com.googlecode.groovycpp.StaticConstructorNode
import com.googlecode.groovycpp.annotations.GlobalAnnotation
import com.googlecode.groovycpp.annotations.LocalAnnotation

@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)
class CPlusPlusTransformation extends BaseTransformation {

	public CPlusPlusTransformation() {
		super(false)
	}

	@Override
	protected void localTransform(AnnotationNode annotations, ClassNode clazz,
			SourceUnit source) {
		def annotation = AnnotationUtility.lookupAnnotation(LocalAnnotation.class, clazz);
		if (annotation) {
			List<MethodNode> staticConstructorList = clazz.getDeclaredMethods("<clinit>")
			MethodNode staticConstructor = staticConstructorList.empty ? null : staticConstructorList[0]
			augmentStaticConstructor(clazz, staticConstructor)
		}
	}

	@Override
	protected void globalTransform(ModuleNode module, SourceUnit source) {
		module.classes*.each { ClassNode clazz ->
			def annotation = AnnotationUtility.lookupAnnotation(GlobalAnnotation.class, clazz);
			if (annotation) {
				MethodNode staticConstructor =
						clazz.methods.flatten().find { it.name.equals("<clinit>") }

				augmentStaticConstructor(clazz, staticConstructor)
			}
		}
	}

	protected augmentStaticConstructor(ClassNode clazz, MethodNode staticConstructor) {
		staticConstructor = staticConstructor?:new StaticConstructorNode()

		new AstBuilder().buildFromCode(CompilePhase.CANONICALIZATION, true) {
			System.out.println("TESTING");
		}.each {
			staticConstructor.code.getStatements().add(it)
		}

		if (staticConstructor instanceof StaticConstructorNode) {
			clazz.addMethod(staticConstructor);
		}

		if (logProgress) {
			println "Augmented static constructor"
			staticConstructor.code.getStatements().each {
				println "Statement: " + it
			}
		}
	}
}
